package com.wstuo.common.jaas.service;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

import org.apache.log4j.Logger;

import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import com.wstuo.common.security.utils.AppConfigUtils;

public class SunOneLDAPLoginConnect {
	private static DirContext ctx;
	private static Hashtable env;
	private static final Logger LOGGER = Logger.getLogger(SunOneLDAPLoginConnect.class);
	
    //验证用户是否存在
	public boolean isUserexist(String uid,String password) {
    	setEnvironment();
    	try {
			ctx = new InitialDirContext(env);
		} catch (NamingException e) {
			// TODO Auto-generated catch block
			LOGGER.error(e);
		}
    	Properties props = new Properties();
    	InputStream in;
    	String JAAS_PATH =  AppConfigUtils.getInstance().getCustomJAASPath();
    	try {
			in = new BufferedInputStream (new FileInputStream(JAAS_PATH+"//sunOne.conf"));
			props.load(in);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			LOGGER.error(e);
		}catch (IOException e) {
			// TODO Auto-generated catch block
			LOGGER.error(e);
		}
    	try {
    		Attributes attrs = ctx.getAttributes("uid=" + uid +"," + props.getProperty("BASE_DN"));
		    if(attrs != null){ 
		    	return isUserPassword(attrs, "userpassword",password);
			}else{ 
		    	return false; 
		    }
	    }catch(NamingException ne) {
	    	return false;
	    }finally{
	    	closeConnection();
	    }
    }
    //设置登录到LDAP服务器的信息
    @SuppressWarnings({ "rawtypes", "unchecked" })
	private void setEnvironment() {
    	Properties props = new Properties();
    	InputStream in;
    	String JAAS_PATH =  AppConfigUtils.getInstance().getCustomJAASPath();
    	try {
			in = new BufferedInputStream (new FileInputStream(JAAS_PATH+"//sunOne.conf"));
			props.load(in);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			LOGGER.error(e);
		}catch (IOException e) {
			// TODO Auto-generated catch block
			LOGGER.error(e);
		}
	    env = new Hashtable();
	    env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
	    env.put(Context.PROVIDER_URL,props.getProperty("LDAP_URL"));
	    env.put(Context.SECURITY_AUTHENTICATION,"simple");
	    env.put(Context.SECURITY_PRINCIPAL,props.getProperty("MANAGER_DN"));
	    env.put(Context.SECURITY_CREDENTIALS,props.getProperty("MANAGER_PASSWORD"));
    }
    //对比密码
    private boolean isUserPassword(Attributes attrs, String attrName, String password)throws NamingException {
    	Attribute attr = attrs.get(attrName);
		byte[] bytes = (byte[]) attr.get(0);
		String passwordValue = new String(bytes);
    	MessageDigest md = null;
		try {
			md = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			LOGGER.error(e);
		}
    	// 取出加密字符
    	if (passwordValue.startsWith("{SSHA}")) {
    		passwordValue = passwordValue.substring(6);
    	} else if (passwordValue.startsWith("{SHA}")) {
    		passwordValue = passwordValue.substring(5);
    	}
    	
    	// 解码BASE64
    	byte[] ldappwbyte = Base64.decode(passwordValue);
    	byte[] shacode;
    	byte[] salt;

    	// 前20位是SHA-1加密段，20位后是最初加密时的随机明文
    	if (ldappwbyte.length <= 20) {
	    	shacode = ldappwbyte;
	    	salt = new byte[0];
    	} else {
	    	shacode = new byte[20];
	    	salt = new byte[ldappwbyte.length - 20];
	    	System.arraycopy(ldappwbyte, 0, shacode, 0, 20);
	    	System.arraycopy(ldappwbyte, 20, salt, 0, salt.length);
    	}
    	// 把用户输入的密码添加到摘要计算信息
    	md.update(password.getBytes());
    	// 把随机明文添加到摘要计算信息
    	md.update(salt);

    	// 按SSHA把当前用户密码进行计算
    	byte[] inputpwbyte = md.digest();

    	// 返回校验结果
    	return MessageDigest.isEqual(shacode, inputpwbyte);
    }
    //关闭到LDAP服务器的连接
    private static void closeConnection() {
	    try {
	    	ctx.close();
	    } catch (NamingException ne) {
	    	LOGGER.error(ne);
	    }
    }
}
